/**
* JSON 工具包
*/

#pragma once

#include <stddef.h>
#include <stdint.h>
#include "std_err.h"

// 可处理的最大 JSON 字段值长度（字符串型值包括引号在内）
#define JSON_VALUE_SIZE_MAX 128


#ifdef __cplusplus
extern "C" {
#endif

/**
 * 简单 JSON 解析: 获取 JSON 字符串表示的 JSON 对象中指定字段的原始值，并以字符串的形式返回
 * @param json JSON 字符串
 * @param field 字段名
 * @return 正常返回字段的原始值（字符串的形式），如数字型的值 "123.45"，字符串型的值 "\"abc\""，对象型的值 "{\"name\":12}"。失败返回 NULL。
 * @attention 返回的字符串值大小最大为 JSON_VALUE_SIZE_MAX；这个字符串缓冲区是此函数内部的 static 变量，所以不要 free() 释放，也不是线程安全的！
 */
const char* json_get_field_raw(const char* json, const char* field);

/**
 * 简单 JSON 解析: 获取 JSON 字符串表示的 JSON 对象中指定数组字段的原始值，并以字符串的形式返回
 * @param json JSON 字符串
 * @param field 字段名（应是一个数组）
 * @return 正常返回字段的原始值（字符串的形式）。失败返回 NULL。
 * @attention 返回的字符串值大小最大为 JSON_VALUE_SIZE_MAX；这个字符串缓冲区是此函数内部的 static 变量，所以不要 free() 释放，也不是线程安全的！
 */
const char* json_get_field_array_raw(const char* json, const char* field, size_t *count);

/**
 * 从一个 JSON 数组字符串中提取数组元素
 * @param str JSON 数组字符串（不包括'[]'）。如: "1,2,3"
 * @param arr 用于接收提取的数组元素的数组
 * @param count arr 中可存放的元素数量
 * @return 实际提取的数组元素数量
 */
size_t json_get_int_array(const char* str, int *arr, size_t count);
size_t json_get_long_array(const char* str, long *arr, size_t count);
size_t json_get_float_array(const char* str, float *arr, size_t count);
size_t json_get_double_array(const char* str, double *arr, size_t count);
static inline size_t json_get_uint_array(const char* str, unsigned int *arr, size_t count) { return json_get_int_array(str, (int*)arr, count); }
static inline size_t json_get_ulong_array(const char* str, unsigned long *arr, size_t count) { return json_get_long_array(str, (long*)arr, count); }

/**
 * 简单 JSON 解析: 获取 JSON 字符串表示的 JSON 对象中指定字符串型字段的值（去掉了前后引号）
 * @param json JSON 字符串
 * @param field 字段名
 * @return 正常返回字段的字符串的形式值（去掉了前后引号），如 "{\"name\":\"abc\"}" 会返回 "abc"。失败返回 NULL。
 * @attention 返回的字符串值大小最大为 JSON_VALUE_SIZE_MAX；这个字符串缓冲区是此函数内部的 static 变量，所以不要 free() 释放，也不是线程安全的！
*/
const char* json_get_field_string(const char* json, const char* field);

/**
 * 简单 JSON 解析: 获取 JSON 字符串表示的字符串列表
 * @param json JSON 字符串。
 * @param max_count 最多提取多少个字符串。
 * @return 字符串列表。最后一个字符串为 NULL。
 * @attention 返回的字符串列表不再使用时需要使用 FREESTRARR() 释放。
*/
const char** json_get_string_array(const char* json, size_t max_count);

/**
* 简单 JSON 解析: 获取 JSON 字符串表示的 JSON 对象中指定字段的值
* @param json JSON 字符串
* @param field 字段名
* @param value [out] 字段的值
* @return 正常返回 STD_ERR_OK，否则返回错误码。
*/
std_err_t json_get_field_int(const char *json, const char *field, int *value);
static inline std_err_t json_get_field_uint(const char *json, const char *field, unsigned int *value) { return json_get_field_int(json, field, (int*)value); }

/**
* 简单 JSON 解析: 获取 JSON 字符串表示的 JSON 对象中指定字段的值
* @param json JSON 字符串
* @param field 字段名
* @param value [out] 字段的值
* @return 正常返回 STD_ERR_OK，否则返回错误码。
*/
std_err_t json_get_field_long(const char *json, const char *field, long *value);
static inline std_err_t json_get_field_ulong(const char *json, const char *field, unsigned long *value) { return json_get_field_long(json, field, (long*)value); }

/**
* 简单 JSON 解析: 获取 JSON 字符串表示的 JSON 对象中指定字段的值
* @param json JSON 字符串
* @param field 字段名
* @param value [out] 字段的值
* @return 正常返回 STD_ERR_OK，否则返回错误码。
*/
std_err_t json_get_field_int64(const char *json, const char *field, int64_t *value);
static inline std_err_t json_get_field_uint64(const char *json, const char *field, uint64_t *value) { return json_get_field_int64(json, field, (int64_t*)value); }

/**
* 简单 JSON 解析: 获取 JSON 字符串表示的 JSON 对象中指定字段的值
* @param json JSON 字符串
* @param field 字段名
* @param value [out] 字段的值
* @return 正常返回 STD_ERR_OK，否则返回错误码。
*/
std_err_t json_get_field_float(const char *json, const char *field, float *value);

/**
* 简单 JSON 解析: 获取 JSON 字符串表示的 JSON 对象中指定字段的值
* @param json JSON 字符串
* @param field 字段名
* @param value [out] 字段的值
* @return 正常返回 STD_ERR_OK，否则返回错误码。
*/
std_err_t json_get_field_double(const char *json, const char *field, double *value);


#ifdef __cplusplus
} // extern "C"
#endif
